﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hourglass.Qrobot.Http;
using Hourglass.Qrobot.Utils;

namespace Hourglass.Qrobot.Models
{
    public static class ModelConvert
    {
        #region ApplyReturned
        public static Friend ApplyReturned(this Friend friend, ReturnedFriendInfo returned)
        {
            friend.NickName = returned.NickName;
            friend.Personal = returned.Personal;
            friend.Gender = SmartEnums.EnumExtensionUtils.ConvertGender(returned.Gender);
            friend.Birthday = returned.Birthday.ToDateTime();
            friend.Zodiac = (SmartEnums.Zodiac)returned.Shengxiao;
            friend.Constel = (SmartEnums.Constel)returned.Constel;
            friend.Blood = (SmartEnums.Blood)returned.Blood;
            friend.Location = new Location(returned.Country, returned.Province, returned.City);
            friend.Phone = returned.Phone;
            friend.Mobile = returned.Mobile;
            friend.Email = returned.Email;
            friend.Homepage = returned.Homepage;
            friend.Occupation = returned.Occupation;
            friend.College = returned.College;
            friend.Face = returned.Face;
            friend.Allow = returned.Allow;

            return friend;
        }

        public static UserInfo ApplyReturned(this UserInfo userInfo, ReturnedUserInfo returned)
        {
            userInfo.Id = returned.Uin;
            userInfo.VipLevel = returned.VipInfo;
            userInfo.Vfwebqq = returned.Vfwebqq;
            userInfo.Signature = returned.Signature;
            userInfo.Qq = returned.Qq;
            userInfo.ClientType = SmartEnums.OnlineClientType.Mobile;
            userInfo.Status = SmartEnums.OnlineStatus.Online;
            userInfo.ApplyReturned((ReturnedFriendInfo)returned);

            return userInfo;
        }

        public static Group ApplyReturned(this Group group, ReturnedGroupInfo.Info returned)
        {
            group.Id = returned.GroupId;
            group.Code = returned.Code;
            group.Class = returned.Class;
            group.Name = returned.Name;
            group.Level = returned.Level;
            group.OwnerQq = returned.OwnerQq;
            group.Memo = returned.Memo;
            group.Option = returned.Option;
            group.Face = returned.Face;
            group.Flag = returned.Flag;
            group.Fingermemo = returned.Fingermemo;
            group.Members = new Dictionary<long, GroupMember>(returned.Members.Count);
            group.CreateTime = TimeHelper.SecondsToDateTime(returned.CreateTime);

            foreach (var member in returned.Members)
            {
                group.Members[member.MemberUin] = new GroupMember(member.MemberUin, member.Flag) {BelongGroup = group};
            }

            return group;
        }

        public static GroupMember ApplyReturned(this GroupMember member, ReturnedGroupInfo.MemberInfo returned)
        {
            member.NickName = returned.NickName;
            member.Gender = SmartEnums.EnumExtensionUtils.ConvertGender(returned.Gender);
            member.Location = new Location(returned.Country, returned.Province, returned.City);

            return member;
        }

        public static Disscuss ApplyReturned(this Disscuss disscuss, ReturnedDisscussInfo.Info returned, QQContext context)
        {
            disscuss.Id = returned.Id;
            disscuss.Name = returned.Name;
            disscuss.Members = new Dictionary<long, DisscussMember>(returned.Members.Count);
            var milliscond = TimeHelper.MilliscondFromSeventy();
            foreach (var member in returned.Members)
            {
                var qq = DataProvider.GetPersonalQq(context.ToAccountNumberRequest<PersonalQqRequest>(member.MemberUin, milliscond));
                disscuss.Members[member.MemberUin] = new DisscussMember
                {
                    Id = member.MemberUin,
                    Ruin = member.RUin,
                    BelongDisscuss = disscuss,
                    Qq = qq
                };
            }

            return disscuss;
        }

        #endregion ApplyReturned

        #region ConvertToView

        public static Group ConvertToView(this ReturnedGroupInfo groupInfo, Group group = null)
        {
            if (group == null)
            {
                group = new Group {Id = groupInfo.GroupInfo.GroupId};
            }
            group.ApplyReturned(groupInfo.GroupInfo);

            foreach (var memberInfo in groupInfo.MemberInfos)
            {
                if (!group.Members.ContainsKey(memberInfo.Uin)) continue;

                var member = group.Members[memberInfo.Uin];
                member.ApplyReturned(memberInfo);
            }

            foreach (var mark in groupInfo.MemberMarks ?? Enumerable.Empty<ReturnedGroupInfo.MemberMark>())
            {
                if (!group.Members.ContainsKey(mark.MemberId)) continue;

                var member = group.Members[mark.MemberId];
                member.GroupCard = mark.MarkName;
            }

            foreach (var onlineInfo in groupInfo.OnlineInfos)
            {
                if (!group.Members.ContainsKey(onlineInfo.Uin)) continue;

                var member = group.Members[onlineInfo.Uin];
                member.ClientType = (SmartEnums.OnlineClientType)onlineInfo.ClientType;
                member.Status = (SmartEnums.OnlineStatus)onlineInfo.Status;
            }

            foreach (var vipInfo in groupInfo.VipInfos)
            {
                if (!group.Members.ContainsKey(vipInfo.Uin)) continue;

                var member = group.Members[vipInfo.Uin];
                member.VipLevel = vipInfo.IsVip == 0 ? 0 : vipInfo.Level;
            }

            return group;
        }

        public static Disscuss ConvertToView(this ReturnedDisscussInfo disscussInfo, QQContext context, Disscuss disscuss = null)
        {
            if (disscuss == null)
            {
                disscuss = new Disscuss {Id = disscussInfo.DisscussInfo.Id};
            }
            disscuss.ApplyReturned(disscussInfo.DisscussInfo, context);

            foreach (var memberInfo in disscussInfo.MemberInfos)
            {
                if (!disscuss.Members.ContainsKey(memberInfo.Uin)) continue;

                var member = disscuss.Members[memberInfo.Uin];
                member.NickName = memberInfo.NickName;
            }

            foreach (var onlineInfo in disscussInfo.OnlineInfos)
            {
                if (!disscuss.Members.ContainsKey(onlineInfo.Uin)) continue;

                var member = disscuss.Members[onlineInfo.Uin];
                member.ClientType = (SmartEnums.OnlineClientType)onlineInfo.ClientType;
                member.Status = SmartEnums.EnumExtensionUtils.ConvertOnlineStatus(onlineInfo.Status);
            }
            return disscuss;
        }

        #endregion ConvertToView

        public static QqMessage ConvertToView(this PollResponse response, QQContext context, out string idOrName)
        {
            idOrName = String.Empty;
            QqMessage message;
            if (response.Result.Count > 0)
            {
                // todo: 记录日志，看看多了些什么
            }
            var result = response.Result[0];
            switch (result.PollType)
            {
                case "discu_message":
                    message = new DisscussMessage();
                    var disscussMember = context.FindOrLoadDisscussMemberById(result.Value.SendUin, result.Value.FromUin);
                    if (disscussMember != null)
                    {
                        message.FromQq = disscussMember.GetPersonInfo();
                        idOrName = disscussMember.BelongDisscuss.Name;
                    }
                    break;
                case "group_message":
                    message = new GroupMessage();
                    var groupMember = context.FindOrLoadGroupMemberById(result.Value.SendUin, result.Value.FromUin);
                    if (groupMember != null)
                    {
                        message.FromQq = groupMember.GetPersonInfo();
                        idOrName = groupMember.BelongGroup.GroupNumber.ToString();
                    }
                    break;
                case "message":
                    message = new PersonalMessage();
                    var friend = context.FindOrLoadFriendById(result.Value.FromUin);
                    if (friend != null)
                    {
                        message.FromQq = friend.GetPersonInfo();
                        idOrName = friend.Qq.ToString();
                    }
                    break;
                case "kick_message":
                    return new KickMessage(response.OfflineMark);
                default:
                    return new ErrorMessage(response.ErrorMessage);
            }
            FillMessageContent(result, message, context);
            if (message.FromQq == null)
            {
                message.FromQq = new QqMessage.PersonInfo {Qq = 0, NickName = "Unknow", MarkName = "Unknow"};
            }

            return message;
        }

        private static void FillMessageContent(PollMessage response, QqMessage message, QQContext context)
        {
            var contents = response.Value.Content;
            if(contents == null || contents.Count == 0) return;

            var fullBuilder = new StringBuilder();
            var noAtBuilder = new StringBuilder();
            for (var i = 1; i < contents.Count; i++)
            {
                var content = contents[i].ToString();
                if (string.IsNullOrWhiteSpace(content)) continue;
                if (content.StartsWith("[")) continue;

                fullBuilder.Append(content);
                if (content.StartsWith("@"))
                {
                    if (message.Type == QqMessage.MessageType.Personal)
                    {
                        noAtBuilder.Append(content);
                    }
                    else if(message.Type == QqMessage.MessageType.Group || message.Type == QqMessage.MessageType.Disscuss)
                    {
                        if (i + 1 < contents.Count && string.IsNullOrEmpty(contents[i + 1].ToString()))
                        {
                            i++;
                            var name = content.Substring(1);
                            List<IPerson> persons = null;
                            if (message.Type == QqMessage.MessageType.Group)
                            {
                                var person = context.FindOrLoadGroupMemberByName(name, response.Value.GroupCode);
                                if (person != null) persons = new List<IPerson> {person};
                                else if (SmartQQ.IsAtAll(name)) persons = context.Qq.GroupManager.Groups[response.Value.GroupCode].Members.Values.ToList<IPerson>();
                            }
                            else
                            {
                                var person = context.FindOrLoadDisscussMemberByName(name, response.Value.DisscussId);
                                if(person != null) persons = new List<IPerson> {person};
                                else if (SmartQQ.IsAtAll(name)) persons = context.Qq.DisscussManager.Disscusses[response.Value.DisscussId].Members.Values.ToList<IPerson>();
                            }
                            if (persons != null)
                            {
                                message.AtQqList.AddRange(persons.Select(p => p.GetPersonInfo()));
                            }
                        }
                        else
                        {
                            noAtBuilder.Append(content);
                        }
                    }
                }
            }
            message.FullContent = fullBuilder.ToString();
            message.NoAtContent = noAtBuilder.ToString();
        }

        #region Recombination

        /// <summary>
        /// 重组好友列表数据
        /// </summary>
        /// <param name="manager">Manager</param>
        /// <param name="context">QQContext</param>
        /// <param name="friends">好友列表信息</param>
        /// <param name="recents">最近联系人</param>
        /// <param name="onlines">在线好友</param>
        /// <param name="friendInfos">好友详细信息</param>
        public static void RecombinationFriends(this FriendsManager manager, QQContext context, ReturnedUserFriends friends, IList<ReturnedRecent> recents, IList<ReturnedOnlineFriend> onlines, IList<ReturnedFriendInfo> friendInfos)
        {
            var milliscond = TimeHelper.MilliscondFromSeventy();
            foreach (var category in friends.Categories)
            {
                // todo: 如果已包含，需要记录日志
                if (manager.Catrgories.ContainsKey(category.Index)) continue;

                manager.Catrgories.Add(category.Index, new FriendCatrgory(category.Index, category.Sort, category.Name));
            }
            foreach (var friend in friends.Friends)
            {
                // todo: 如果已包含，需要记录日志
                if (manager.Friends.ContainsKey(friend.Uin)) continue;

                var category = manager.Catrgories[friend.CategoryId];
                var qfriend = new Friend { Id = friend.Uin, Catrgory = category, Flag = friend.Flag };
                category.Friends.Add(qfriend.Id, qfriend);
                manager.Friends.Add(friend.Uin, qfriend);
            }
            foreach (var markName in friends.MarkNames)
            {
                if (!manager.Friends.ContainsKey(markName.Uin)) continue;

                // todo: 记录日志，如果用户已设置marknameType，则记录日志
                var friend = manager.Friends[markName.Uin];
                friend.MarkNameType = markName.Type;
                friend.MarkName = markName.Name;
            }
            foreach (var vipInfo in friends.VipInfos)
            {
                if (!manager.Friends.ContainsKey(vipInfo.Uin)) continue;

                // todo: 记录日志，isvip可能不是0和1，此种情况记录日志
                var friend = manager.Friends[vipInfo.Uin];
                friend.VipLevel = vipInfo.IsVip == 0 ? 0 : vipInfo.Level;
            }
            foreach (var info in friends.Infos)
            {
                if (!manager.Friends.ContainsKey(info.Uin)) continue;

                // todo: 记录日志，可能希望在这里记录face和flag的值进行分析值的意思
                var friend = manager.Friends[info.Uin];
                friend.Face = info.Face;
                friend.Flag = info.Flag;
                friend.NickName = info.NickName;
            }
            foreach (var recent in recents.Where(r => r.Type.Equals((int)SmartEnums.RecentType.Friend)))
            {
                if (!manager.Friends.ContainsKey(recent.Uin)) continue;

                manager.Friends[recent.Uin].IsRecent = true;
            }
            foreach (var online in onlines)
            {
                if (!manager.Friends.ContainsKey(online.Uin)) continue;

                var friend = manager.Friends[online.Uin];
                friend.ClientType = (SmartEnums.OnlineClientType)online.ClientType;
                friend.Status = SmartEnums.EnumExtensionUtils.ConvertOnlineStatus(online.Status);
            }
            foreach (var friendInfo in friendInfos)
            {
                // todo: 如果不包含，需要记录日志
                if (!manager.Friends.ContainsKey(friendInfo.Uin)) continue;

                var friend = manager.Friends[friendInfo.Uin];
                friend.ApplyReturned(friendInfo);

                friend.Qq = DataProvider.GetPersonalQq(context.ToAccountNumberRequest<PersonalQqRequest>(friend.Id, milliscond));
            }
        }

        /// <summary>
        /// 重组数据
        /// </summary>
        public static void RecombinationGroups(this GroupsManager manager, QQContext context, ReturnedGroups groups, IList<ReturnedGroupInfo> groupInfos)
        {
            // todo: 如果groups中的Masks和Marks属性有值得话，需要记录日志
            var milliscond = TimeHelper.MilliscondFromSeventy();
            foreach (var group in groups.Names)
            {
                manager.Groups.Add(group.Id, new Group(group.Id, group.Code, group.Flag, group.Name));
            }
            foreach (var groupInfo in groupInfos)
            {
                if (!manager.Groups.ContainsKey(groupInfo.GroupInfo.GroupId)) continue;

                var group = manager.Groups[groupInfo.GroupInfo.GroupId];
                groupInfo.ConvertToView(group);

                group.GroupNumber = DataProvider.GetGroupNumber(context.ToAccountNumberRequest<GroupNumberRequest>(group.Code, milliscond));
            }
        }

        /// <summary>
        /// 数据重组
        /// </summary>
        public static void RecombinationDisscusses(this DisscussesManager manager, QQContext context, ReturnedDisscusses disscusses, List<ReturnedDisscussInfo> disscussInfos)
        {
            foreach (var disscuss in disscusses.Disscusses)
            {
                manager.Disscusses.Add(disscuss.Id, new Disscuss(disscuss.Name));
            }

            foreach (var disscussInfo in disscussInfos)
            {
                if (!manager.Disscusses.ContainsKey(disscussInfo.DisscussInfo.Id)) continue;

                var disscuss = manager.Disscusses[disscussInfo.DisscussInfo.Id];
                disscuss.ApplyReturned(disscussInfo.DisscussInfo, context);

                foreach (var memberInfo in disscussInfo.MemberInfos)
                {
                    if (!disscuss.Members.ContainsKey(memberInfo.Uin)) continue;

                    var member = disscuss.Members[memberInfo.Uin];
                    member.NickName = memberInfo.NickName;
                }

                foreach (var onlineInfo in disscussInfo.OnlineInfos)
                {
                    if (!disscuss.Members.ContainsKey(onlineInfo.Uin)) continue;

                    var member = disscuss.Members[onlineInfo.Uin];
                    member.ClientType = (SmartEnums.OnlineClientType)onlineInfo.ClientType;
                    member.Status = SmartEnums.EnumExtensionUtils.ConvertOnlineStatus(onlineInfo.Status);
                }
            }
        }

        #endregion Recombination
    }
}
